<template>
  <div class="editor-panel">
    <el-tabs v-model="activeTabLocal" class="editor-tabs" @tab-change="handleTabChange">
      <el-tab-pane label="顶点着色器" name="vertex">
        <div ref="vertexEditorContainer" class="editor-container"></div>
      </el-tab-pane>
      <el-tab-pane label="片元着色器" name="fragment">
        <div ref="fragmentEditorContainer" class="editor-container"></div>
      </el-tab-pane>
      <el-tab-pane label="JavaScript代码" name="javascript">
        <div ref="jsEditorContainer" class="editor-container"></div>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, nextTick, watch, onBeforeUnmount } from 'vue'
import * as monaco from 'monaco-editor'

interface Props {
  vertexCode: string
  fragmentCode: string
  jsCode: string
  activeTab?: string
}

interface Emits {
  (e: 'update:vertexCode', value: string): void
  (e: 'update:fragmentCode', value: string): void
  (e: 'update:jsCode', value: string): void
  (e: 'update:activeTab', value: string): void
}

const props = withDefaults(defineProps<Props>(), {
  activeTab: 'vertex'
})

const emit = defineEmits<Emits>()

const vertexEditorContainer = ref<HTMLDivElement | null>(null)
const fragmentEditorContainer = ref<HTMLDivElement | null>(null)
const jsEditorContainer = ref<HTMLDivElement | null>(null)

const activeTabLocal = ref(props.activeTab)

let vertexEditor: monaco.editor.IStandaloneCodeEditor | null = null
let fragmentEditor: monaco.editor.IStandaloneCodeEditor | null = null
let jsEditor: monaco.editor.IStandaloneCodeEditor | null = null

// 编辑器配置
const editorOptions: monaco.editor.IStandaloneEditorConstructionOptions = {
  fontSize: 14,
  minimap: { enabled: false },
  scrollBeyondLastLine: false,
  automaticLayout: true,
  theme: 'vs-dark',
  readOnly: false,
}

// 初始化编辑器
const initEditors = () => {
  nextTick(() => {
    // 顶点着色器编辑器
    if (vertexEditorContainer.value && !vertexEditor) {
      vertexEditor = monaco.editor.create(vertexEditorContainer.value, {
        value: props.vertexCode,
        language: 'glsl',
        ...editorOptions
      })
      vertexEditor.onDidChangeModelContent(() => {
        const value = vertexEditor?.getValue() || ''
        emit('update:vertexCode', value)
      })
    }

    // 片元着色器编辑器
    if (fragmentEditorContainer.value && !fragmentEditor) {
      fragmentEditor = monaco.editor.create(fragmentEditorContainer.value, {
        value: props.fragmentCode,
        language: 'glsl',
        ...editorOptions
      })
      fragmentEditor.onDidChangeModelContent(() => {
        const value = fragmentEditor?.getValue() || ''
        emit('update:fragmentCode', value)
      })
    }

    // JavaScript编辑器
    if (jsEditorContainer.value && !jsEditor) {
      jsEditor = monaco.editor.create(jsEditorContainer.value, {
        value: props.jsCode,
        language: 'javascript',
        ...editorOptions
      })
      jsEditor.onDidChangeModelContent(() => {
        const value = jsEditor?.getValue() || ''
        emit('update:jsCode', value)
      })
    }
  })
}

// 更新编辑器值
const updateEditorValue = (
  editor: monaco.editor.IStandaloneCodeEditor | null,
  newValue: string
) => {
  if (editor && editor.getValue() !== newValue) {
    editor.setValue(newValue)
  }
}

// 监听外部代码变化
watch(() => props.vertexCode, (newValue) => {
  updateEditorValue(vertexEditor, newValue)
})

watch(() => props.fragmentCode, (newValue) => {
  updateEditorValue(fragmentEditor, newValue)
})

watch(() => props.jsCode, (newValue) => {
  updateEditorValue(jsEditor, newValue)
})

// 监听activeTab变化
watch(() => props.activeTab, (newValue) => {
  activeTabLocal.value = newValue
})

watch(activeTabLocal, (newValue) => {
  emit('update:activeTab', newValue)
})

// 处理标签页切换
const handleTabChange = () => {
  nextTick(() => {
    vertexEditor?.layout()
    fragmentEditor?.layout()
    jsEditor?.layout()
  })
}

// 暴露给父组件的方法
defineExpose({
  setVertexCode: (code: string) => {
    updateEditorValue(vertexEditor, code)
  },
  setFragmentCode: (code: string) => {
    updateEditorValue(fragmentEditor, code)
  },
  setJsCode: (code: string) => {
    updateEditorValue(jsEditor, code)
  }
})

onMounted(() => {
  initEditors()
})

onBeforeUnmount(() => {
  vertexEditor?.dispose()
  fragmentEditor?.dispose()
  jsEditor?.dispose()
})
</script>

<style lang="scss" scoped>
.editor-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  background-color: #1e1e1e;
  border-radius: 4px;
  overflow: hidden;

  .editor-tabs {
    height: 100%;
    
    :deep(.el-tabs__header) {
      background-color: #252526;
      margin: 0;
      padding: 0 10px;
    }

    :deep(.el-tabs__nav-wrap::after) {
      display: none;
    }

    :deep(.el-tabs__item) {
      color: #969696;
      
      &.is-active {
        color: #fff;
      }
    }

    :deep(.el-tabs__content) {
      height: calc(100% - 40px);
      padding: 0;
    }

    :deep(.el-tab-pane) {
      height: 100%;
    }
  }

  .editor-container {
    height: 100%;
    width: 100%;
  }
}

:deep(.monaco-editor) {
  .margin {
    background-color: #1e1e1e !important;
  }
}
</style>

